// ignore_for_file: constant_identifier_names

import 'dart:convert';
import 'dart:typed_data';

import 'package:dio/dio.dart';

import 'package:oktoast/oktoast.dart';
import 'package:video_setting/pages/utils/toast_utils.dart';

class HttpUtil {
  static const String GET = 'get';
  static const String POST = 'post';
  static const String PUT = 'put';
  static const String PATCH = 'patch';
  static const String DELETE = 'delete';

  late Dio _dio;
  CancelToken cancelToken = CancelToken();
  HttpUtil(Dio dio) {
    _dio = dio;
  }

  get(String path, {Map<String, dynamic>? data, CancelToken? cancelToken, Options? options}) async {
    Response? response;
    try {
      response = await _dio.get(path, queryParameters: data, cancelToken: cancelToken, options: options);
    } on DioError catch (e) {
      ToastUtil.show(formatError(e));
    }

    return response;
  }

  post(String path, {Map<String, dynamic>? data, CancelToken? cancelToken, Options? options}) async {
    Response response;
    try {
      response = await _dio.post(path, data: data, cancelToken: cancelToken, options: options);
    } on DioError catch (e) {
      /// 响应信息, 如果错误发生在在服务器返回数据之前，它为 `null`
      ToastUtil.show(formatError(e));
      rethrow;
    }
    return response;
  }

  postFormData(String path, {FormData? data, CancelToken? cancelToken, Options? options}) async {
    Response response;
    try {
      response = await _dio.post(path, data: data, cancelToken: cancelToken, options: options);
    } on DioError catch (e) {
      /// 响应信息, 如果错误发生在在服务器返回数据之前，它为 `null`
      ToastUtil.show(formatError(e));
      rethrow;
    }
    return response;
  }

  postBodyOnly(String path, {dynamic data, CancelToken? cancelToken, Options? options}) async {
    Response response;
    try {
      response = await _dio.post(path, data: data, cancelToken: cancelToken, options: options);
    } on DioError catch (e) {
      /// 响应信息, 如果错误发生在在服务器返回数据之前，它为 `null`
      ToastUtil.show(formatError(e));
      rethrow;
    }
    return response;
  }

  postFetchByte(String path, {Map<String, dynamic>? data, CancelToken? cancelToken, Options? options}) async {
    Uint8List bytes;

    try {
      Response response = await _dio.post(path, data: data, cancelToken: cancelToken, options: options);
      bytes = _consolidateHttpClientResponseBytes(response.data);
    } on DioError catch (e) {
      /// 响应信息, 如果错误发生在在服务器返回数据之前，它为 `null`
      ToastUtil.show(formatError(e));
      rethrow;
    }
    return bytes;
  }

  /// 取消请求
  ///
  /// 同一个cancel token 可以用于多个请求，当一个cancel token取消时，所有使用该cancel token的请求都会被取消。所以参数可选
  void cancelRequests(CancelToken token) {
    token.cancel("cancelled");
  }

  _consolidateHttpClientResponseBytes(List<int> data) {
    // response.contentLength is not trustworthy when GZIP is involved
    // or other cases where an intermediate transformer has been applied
    // to the stream.
    final List<List<int>> chunks = <List<int>>[];
    int contentLength = 0;
    chunks.add(data);
    contentLength += data.length;
    final Uint8List bytes = Uint8List(contentLength);
    int offset = 0;
    for (List<int> chunk in chunks) {
      bytes.setRange(offset, offset + chunk.length, chunk);
      offset += chunk.length;
    }
    return bytes;
  }

  /// error统一处理
  String formatError(DioError e) {
    return "因网络原因，服务超时，请稍后再试(${e.response?.statusCode})";
  }

  /// 判断返回的是否是200
  static bool isResponse200(Response res) {
    if (res.data != null) {
      var jsonRes;
      if (res.data is String) {
        jsonRes = json.decode(res.data);
      } else if (res.data is Map) {
        jsonRes = res.data;
      }

      if (jsonRes['code'] == 200) {
        return true;
      } else {
        // ToastUtil.show(jsonRes['msg']);
      }
    }
    return false;
  }
}
